Use case: DMA2D CLUT loading in polling mode

In HAL1, there are two ways for loading the CLUT:

  • Either use HAL_DMA2D_CLUTStartLoad() in polling mode or HAL_DMA2D_CLUTStartLoad_IT() in interrupt mode followed by HAL_DMA2D_PollForTransfer() to wait for the completion of the CLUT loading.

  • Alternatively, use HAL_DMA2D_CLUTLoad(), or HAL_DMA2D_ConfigCLUT() followed by HAL_DMA2D_EnableCLUT() in polling mode. If using interrupt mode, use HAL_DMA2D_CLUTLoad_IT(). Then, HAL_DMA2D_PollForTransfer() should be called to wait for the completion of the CLUT loading. Note that this option is considered obsolete in HAL1 itself.

In HAL2, the CLUT transfer configuration is managed by HAL_DMA2D_StartCLUTLoad() in polling mode, or HAL_DMA2D_StartCLUTLoad_IT() if using interrupt mode. Furthermore, the polling function is split: HAL_DMA2D_PollForCLUTLoad() to wait for the CLUT loading completion and HAL_DMA2D_PollForTransfer() to wait for the completion of standard data loading.

Sequence diagram

DMA2D CLUT loading in polling mode.

@startuml
== DMA2D Initialization ==
"Application" -> "DMA2D Driver" : HAL_DMA2D_Init()
"DMA2D Driver" --> "Application" :
== DMA2D CLUT Loading ==
"Application" -> "DMA2D Driver" : HAL_DMA2D_ConfigCLUT()
"DMA2D Driver" --> "Application" :
"Application" -> "DMA2D Driver" : HAL_DMA2D_EnableCLUT()
"DMA2D Driver" --> "Application" :
"Application" -> "DMA2D Driver" : HAL_DMA2D_PollForTransfer()
"DMA2D Driver" --> "Application" :
== DMA2D Layer Configuration ==

@enduml

Code snippet

HAL1

HAL2

const uint32_t ARGB8888_Tab[256] = { .
                                     .
                                     .
                                     0xEFFFFFF2, 0xAB1FFFF0,
                                     0x0504044E, 0x89ADCDEF,
                                     0x15248722, 0x5201245E,
                                     0x01025FDE, 0xFE010203,
                                     0xEFFFFFF2, 0xAB1FFFF0,
                                     0x0504044E, 0x89ADCDEF,
                                     0x15248722, 0x5201245E,
                                     0x01025FDE, 0xFE010203};
uint32_t CLUT_8[256] = { .
                         .
                         .
                         0xC0C0, 0x20C0C0, 0x40C0C0,
                         0x60C0C0, 0x80C0C0, 0xA0C0C0,
                         0xFFFBF0, 0xA0A0A4, 0x808080,
                         0xFF0000, 0xFF00, 0xFFFF00,
                         0xFF, 0xFF00FF, 0xFFFF, 0xFFFFFF};
uint32_t L8_result[1024];

DMA2D_HandleTypeDef hdma2d;
DMA2D_CLUTCfgTypeDef CLUTCfg;

hdma2d.Instance = DMA2D;
hdma2d.Init.Mode = DMA2D_M2M_PFC;
hdma2d.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
hdma2d.Init.OutputOffset = 0x0;
hdma2d.Init.AlphaInverted = DMA2D_REGULAR_ALPHA;
hdma2d.Init.RedBlueSwap = DMA2D_RB_REGULAR;
hdma2d.Init.BytesSwap = DMA2D_BYTES_REGULAR;
hdma2d.Init.LineOffsetMode = DMA2D_LOM_BYTES;


hdma2d.LayerCfg[DMA2D_FOREGROUND_LAYER].InputColorMode = DMA2D_INPUT_AL88;
hdma2d.LayerCfg[DMA2D_FOREGROUND_LAYER].InputOffset = 0;
hdma2d.LayerCfg[DMA2D_FOREGROUND_LAYER].AlphaMode = DMA2D_NO_MODIF_ALPHA;
hdma2d.LayerCfg[DMA2D_FOREGROUND_LAYER].InputAlpha = 0xFF;
hdma2d.LayerCfg[DMA2D_FOREGROUND_LAYER].AlphaInverted = DMA2D_REGULAR_ALPHA;
hdma2d.LayerCfg[DMA2D_FOREGROUND_LAYER].RedBlueSwap = DMA2D_RB_REGULAR;



CLUTCfg.pCLUT = (uint32_t *)CLUT_8;
CLUTCfg.CLUTColorMode = DMA2D_CCM_ARGB8888;
CLUTCfg.Size = 255;

HAL_DMA2D_Init(&hdma2d);
HAL_DMA2D_ConfigCLUT(&hdma2d, CLUTCfg, DMA2D_FOREGROUND_LAYER);
HAL_DMA2D_EnableCLUT(&hdma2d, DMA2D_FOREGROUND_LAYER);
HAL_DMA2D_PollForTransfer(&hdma2d, 10);
const uint32_t ARGB8888_Tab[256] = { .
                                     .
                                     .
                                     0xEFFFFFF2, 0xAB1FFFF0,
                                     0x0504044E, 0x89ADCDEF,
                                     0x15248722, 0x5201245E,
                                     0x01025FDE, 0xFE010203,
                                     0xEFFFFFF2, 0xAB1FFFF0,
                                     0x0504044E, 0x89ADCDEF,
                                     0x15248722, 0x5201245E,
                                     0x01025FDE, 0xFE010203};
uint32_t CLUT_8[256] = { .
                         .
                         .
                         0xC0C0, 0x20C0C0, 0x40C0C0,
                         0x60C0C0, 0x80C0C0, 0xA0C0C0,
                         0xFFFBF0, 0xA0A0A4, 0x808080,
                         0xFF0000, 0xFF00, 0xFFFF00,
                         0xFF, 0xFF00FF, 0xFFFF, 0xFFFFFF};
uint32_t L8_result[1024];

hal_dma2d_handle_t hdma2d;
hal_dma2d_clut_config_t p_clut_conf;
hal_dma2d_mem_copy_config_t p_config;

p_config.output.p_dest = (void const*) (uint32_t)&L8_result;
p_config.output.color_mode = HAL_DMA2D_OUTPUT_COLOR_ARGB8888;
p_config.output.offset = 0x0;





p_config.input.p_src = (void const*) (uint32_t)&ARGB8888_Tab;
p_config.input.color_mode = HAL_DMA2D_INPUT_COLOR_AL88;
p_config.input.offset = 0;
p_config.input.alpha_mode = HAL_DMA2D_INPUT_ALPHA_NO_MODIF;
p_config.input.alpha_value = 0xFF;


p_config.width = 16;
p_config.height = 32;

p_clut_conf.p_clut = (uint32_t *)CLUT_8;
p_clut_conf.color_mode = HAL_DMA2D_CLUT_COLOR_ARGB8888;
p_clut_conf.size = 255;

HAL_DMA2D_Init(&hdma2d, HAL_DMA2D);
HAL_DMA2D_StartCLUTLoad(&hdma2d, &p_clut_conf, HAL_DMA2D_INPUT_FG);

HAL_DMA2D_PollForCLUTLoad(&hdma2d, HAL_DMA2D_INPUT_FG, 10);

Note

  • The DMA2D CLUT loading use case in interrupt mode is similar to the polling-mode use case; the function calls are simply replaced with their interrupt-mode counterparts.

  • For example instead of using HAL_DMA2D_StartCLUTLoad() in polling mode, use HAL_DMA2D_StartCLUTLoad_IT() in interrupt mode.

Key changes

  1. In HAL2, CLUT loading is configured and started using HAL_DMA2D_StartCLUTLoad(), and the completion is polled using HAL_DMA2D_PollForCLUTLoad().

  2. In HAL2, HAL_DMA2D_PollForTransfer() is used to poll standard data transfers (not CLUT loading).